﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Tao.FreeGlut;
using Tao.OpenGl;
using Tarea2Raytracing;
using SceneLib;

namespace Tarea1
{
    class Program
    {
        private static int WIDTH = 400;
        private static int HEIGHT = 400;

        private static int mode = 3;

        private static OpenGLRenderer openGLrenderer;
        private static RaytraceRenderer raytraceRenderer;
        private static RasterizationRenderer rasterizationRenderer;
        private static Scene scene;

        static void Main(string[] args)
        {
            Glut.glutInit();
            Glut.glutInitDisplayMode(Glut.GLUT_SINGLE | Glut.GLUT_RGB);

            Glut.glutInitWindowSize(WIDTH, HEIGHT);
            Glut.glutInitWindowPosition(100, 100);
            Glut.glutCreateWindow("Tarea 2");

            Init();

            Glut.glutDisplayFunc(new Glut.DisplayCallback(Draw));
            Glut.glutIdleFunc(new Glut.IdleCallback(Update));

            Glut.glutKeyboardFunc(new Glut.KeyboardCallback(KeyboardHandle));

            Glut.glutMainLoop();

        }

        static void Init()
        {
            scene = new Scene(WIDTH, HEIGHT);
            scene.Load("output.xml");
            openGLrenderer = new OpenGLRenderer(scene, WIDTH, HEIGHT);
            raytraceRenderer = new RaytraceRenderer(scene, WIDTH, HEIGHT);
            rasterizationRenderer = new RasterizationRenderer(scene, WIDTH, HEIGHT);
        }

        static void Draw()
        {
            if (mode == 1)
            {
                openGLrenderer.Render();
            }
            else if (mode == 2)
            {
                raytraceRenderer.Render();
            }
            else if (mode == 3)
            {
                rasterizationRenderer.Render();
            }
        }

        static void Update()
        {
            if (mode == 2)
            {
                raytraceRenderer.Update();
            }
        }

        static void KeyboardHandle(byte key, int x, int y)
        {
            SceneCamera sceneCam = scene.Camera;
            Vector dir = sceneCam.Target - sceneCam.Position;
            float tar_posDist = dir.Magnitude3();
            dir.Normalize3();
            Vector right = Vector.Cross3(dir, sceneCam.Up);
            float camSpeed = 0.5f;
            Vector tempVec;
            float turnSpeed = 0.1f;

            if (key == 49)
            {
                mode = 1;
                Glut.glutPostRedisplay();
            }
            else if (key == 50)
            {
                mode = 2;
                raytraceRenderer.ResetTracer();
                Glut.glutPostRedisplay();
            }
            else if (key == 51)
            {
                mode = 3;
                Glut.glutPostRedisplay();
            }
            else if (key == (byte)'w')
            {
                scene.Camera.Position += dir * camSpeed;
                scene.Camera.Target += dir * camSpeed;
                Glut.glutPostRedisplay();
            }
            else if (key == (byte)'s')
            {
                scene.Camera.Position -= dir * camSpeed;
                scene.Camera.Target -= dir * camSpeed;
                Glut.glutPostRedisplay();
            }
            else if (key == (byte)'a')
            {
                scene.Camera.Position -= right * camSpeed;
                scene.Camera.Target -= right * camSpeed;
                Glut.glutPostRedisplay();
            }
            else if (key == (byte)'d')
            {
                scene.Camera.Position += right * camSpeed;
                scene.Camera.Target += right * camSpeed;
                Glut.glutPostRedisplay();
            }
            else if (key == (byte)'i')
            {
                tempVec = dir + scene.Camera.Up * turnSpeed;
                tempVec.Normalize3();
                scene.Camera.Target = scene.Camera.Position + tempVec * tar_posDist;
                scene.Camera.Up = Vector.Cross3(right, tempVec);
                Glut.glutPostRedisplay();
            }
            else if (key == (byte)'k')
            {
                tempVec = dir - scene.Camera.Up * turnSpeed;
                tempVec.Normalize3();
                scene.Camera.Target = scene.Camera.Position + tempVec * tar_posDist;
                scene.Camera.Up = Vector.Cross3(right, tempVec);
                Glut.glutPostRedisplay();
            }
            else if (key == (byte)'j')
            {
                tempVec = dir - right * turnSpeed;
                tempVec.Normalize3();
                scene.Camera.Target = scene.Camera.Position + tempVec * tar_posDist;
                Glut.glutPostRedisplay();
            }
            else if (key == (byte)'l')
            {
                tempVec = dir + right * turnSpeed;
                tempVec.Normalize3();
                scene.Camera.Target = scene.Camera.Position + tempVec * tar_posDist;
                Glut.glutPostRedisplay();
            }
        }
    }
}
